home *** CD-ROM | disk | FTP | other *** search
- /* GetDevicesToTest.c */
- /*
- * GetDevicesToTest.c
- * Copyright © 93 Apple Computer Inc. All Rights Reserved.
- *
- * Run the dialog until the user has had enough.
- */
- #include "SCSIAsyncSample.h"
- #include "DialogUtilities.h"
- #include "SCSIDefinitions.h"
-
-
- void SetupDialog(void);
- void MakeNewInfoRecord(void);
- void RefreshParamBlock(void);
- void RefreshDeviceInfo(void);
- Boolean CheckInfoRecord(void);
- void SaveInfoRecord(void);
- OSErr SetupGetSCSIParamBlock(void);
- OSErr SetupDeviceInquiry(void);
- OSErr SetupReadCapacity(void);
- void StoreDeviceString(
- unsigned char *dst,
- unsigned char *src,
- short srcLength
- );
- unsigned long GetFourBytes(
- unsigned char *src
- );
-
- /*
- * These are state flags that are valid only for the current
- * dialog.
- */
- DialogPtr gDialog;
- InfoPtr gCurrentInfoPtr;
- #define INFO (*gCurrentInfoPtr)
- short gThreadIndex;
-
- void
- GetDevicesToTest(void)
- {
- GrafPtr savePort;
- short itemHit;
- Boolean needNewInfoRecord;
- Boolean needToRefreshDeviceInfo;
- Boolean needToRefreshParamBlock;
- Boolean needToUpdateDialogValues;
-
- GetPort(&savePort);
- gDialog = GetNewDialog(DLOG_Query, NULL, (WindowPtr) -1L);
- SetCheckBox(gDialog, kQueryEnableAsync, FALSE);
- SetCheckBox(gDialog, kQueryEnableDisconnect, FALSE);
- SetDialogValue(gDialog, kQueryTotalRequests, 100);
- /*
- * For my system: prime the device to point to the CD-Rom
- */
- SetDialogValue(gDialog, kQueryHostBus, 1);
- SetDialogValue(gDialog, kQueryTargetID, 3);
- /* */
- ShowWindow(gDialog);
- SetPort(gDialog);
- gThreadIndex = 0;
- needNewInfoRecord = TRUE;
- InitCursor();
- for (;;) {
- if (needNewInfoRecord) {
- MakeNewInfoRecord();
- needNewInfoRecord = FALSE;
- needToRefreshParamBlock = TRUE;
- needToUpdateDialogValues = TRUE;
- }
- if (needToRefreshParamBlock) {
- RefreshParamBlock();
- needToRefreshParamBlock = FALSE;
- needToRefreshDeviceInfo = (INFO.pb != NULL);
- needToUpdateDialogValues = TRUE;
- }
- if (needToRefreshDeviceInfo) {
- RefreshDeviceInfo();
- needToRefreshDeviceInfo = FALSE;
- needToUpdateDialogValues = TRUE;
- }
- if (needToUpdateDialogValues) {
- SetupDialog();
- needToUpdateDialogValues = FALSE;
- }
- ModalDialog(NumericFilter, &itemHit);
- switch (itemHit) {
- case kQueryTest:
- if (CheckInfoRecord()) {
- SaveInfoRecord();
- needNewInfoRecord = TRUE;
- }
- break;
- case kQueryFinished:
- if (gCurrentInfoPtr != NULL)
- DisposePtr((Ptr) gCurrentInfoPtr);
- goto exit;
- case kQueryHostBus:
- INFO.deviceIdent.bus = GetDialogValue(gDialog, kQueryHostBus);
- needToRefreshParamBlock = TRUE;
- break;
- case kQueryTargetID:
- INFO.deviceIdent.targetID = GetDialogValue(gDialog, kQueryTargetID);
- needToRefreshDeviceInfo = TRUE;
- break;
- case kQueryEnableAsync:
- SelectCheckBox(gDialog, kQueryEnableAsync, &INFO.enableAsync);
- break;
- case kQueryEnableDisconnect:
- SelectCheckBox(gDialog, kQueryEnableDisconnect, &INFO.enableDisconnect);
- break;
- case kQueryRandomSeek:
- SelectCheckBox(gDialog, kQueryRandomSeek, &INFO.enableRandomSeek);
- break;
- case kQueryTotalRequests:
- INFO.totalTransfers = GetDialogValue(gDialog, kQueryTotalRequests);
- break;
- case kQueryBlocksPerTransfer:
- INFO.transferSizeBlocks = GetDialogValue(gDialog, kQueryBlocksPerTransfer);
- break;
- case kQueryTimeout:
- INFO.completionTimeout = GetDialogValue(gDialog, kQueryTimeout);
- default:
- break;
- }
- }
- exit: ;
- DisposDialog(gDialog);
- SetPort(savePort);
- }
-
- /*
- * MakeNewInfoRecord creates a new, empty, InfoRecord and sets state flags
- * so that the first call to SetupDialog fills in the information.
- */
- void
- MakeNewInfoRecord(void)
- {
- Str255 work;
-
- gCurrentInfoPtr = (InfoPtr) NewPtrClear(sizeof (InfoRecord));
- if (gCurrentInfoPtr == NULL)
- FatalError(MemError(), "\pCan't make new InfoRecord");
- ++gThreadIndex;
- INFO.threadIndex = gThreadIndex;
- INFO.deviceActive = FALSE;
- INFO.testCompleted = FALSE;
- INFO.completionTimeout = (60L * 15L); /* 15 seconds */
- /*
- * Copy the current dialog parameters into the new info record.
- */
- INFO.deviceIdent.bus = GetDialogValue(gDialog, kQueryHostBus);
- INFO.deviceIdent.targetID = GetDialogValue(gDialog, kQueryTargetID);
- INFO.totalTransfers = GetDialogValue(gDialog, kQueryTotalRequests);
- INFO.transferSizeBlocks = GetDialogValue(gDialog, kQueryBlocksPerTransfer);
- INFO.completionTimeout = GetDialogValue(gDialog, kQueryTimeout);
- INFO.enableAsync = GetDialogButton(gDialog, kQueryEnableAsync) == kCheckedButton;
- INFO.enableDisconnect = GetDialogButton(gDialog, kQueryEnableDisconnect) == kCheckedButton;
- INFO.enableRandomSeek = GetDialogButton(gDialog, kQueryRandomSeek) == kCheckedButton;
- GetDateTime(&INFO.randomSeed);
- INFO.randomSeed ^= TickCount();
- NumToString(INFO.threadIndex, work);
- pstrcat(work, "\p Thread index");
- SetDialogText(gDialog, kQueryThreadNumber, work);
- }
-
- /*
- * SetupDialog is executed each time through the dialog loop to enable and
- * disable editable items and to get information about the active device.
- */
- void
- SetupDialog(void)
- {
- EnableDialogItem(gDialog, kQueryTest, INFO.validDevice);
- EnableDialogItem(gDialog, kQueryTotalRequests, INFO.validDevice);
- EnableDialogItem(gDialog, kQueryBlocksPerTransfer, INFO.validDevice);
- EnableDialogItem(gDialog, kQueryTimeout, INFO.validDevice);
- EnableDialogItem(gDialog, kQueryEnableAsync, INFO.validDevice);
- EnableDialogItem(gDialog, kQueryEnableDisconnect, INFO.validDevice);
- if (INFO.validDevice) {
- SetDialogValue(gDialog, kQueryBlocksPerTransfer, INFO.transferSizeBlocks);
- SetDialogValue(gDialog, kQueryTimeout, INFO.completionTimeout);
- SetDialogText(gDialog, kQueryVendorID, (StringPtr) INFO.vendor);
- SetDialogText(gDialog, kQueryProduct, (StringPtr) INFO.product);
- SetDialogValue(gDialog, kQueryLogicalBlockLength, INFO.logicalBlockLength);
- SetDialogValue(gDialog, kQueryBlocksOnDevice, INFO.totalLogicalBlocks);
- }
- else {
- SetDialogText(gDialog, kQueryBlocksPerTransfer, "\p");
- SetDialogText(gDialog, kQueryTimeout, "\p");
- SetDialogText(gDialog, kQueryVendorID, "\p");
- SetDialogText(gDialog, kQueryProduct, "\p");
- SetDialogText(gDialog, kQueryLogicalBlockLength, "\p");
- SetDialogText(gDialog, kQueryBlocksOnDevice, "\p");
- }
- }
-
- void
- RefreshDeviceInfo(void)
- {
- OSErr status;
-
- if (INFO.pb != NULL) {
- status = SetupDeviceInquiry();
- if (status == noErr)
- status = SetupReadCapacity();
- INFO.validDevice = (status == noErr);
- }
- }
-
- /*
- * Return TRUE if the InfoRecord is valid - this allocates the data buffer.
- */
- Boolean
- CheckInfoRecord(void)
- {
- Str15 work;
-
- if (INFO.validDevice == FALSE)
- return (FALSE);
- else {
- INFO.totalTransfers = GetDialogValue(gDialog, kQueryTotalRequests);
- INFO.transferSizeBlocks = GetDialogValue(gDialog, kQueryBlocksPerTransfer);
- INFO.completionTimeout = GetDialogValue(gDialog, kQueryTimeout);
- INFO.bufferLength = (INFO.transferSizeBlocks * INFO.logicalBlockLength);
- INFO.bufferPtr = NewPtr(INFO.bufferLength);
- if (INFO.bufferPtr == NULL) {
- NumToString(INFO.bufferLength, work);
- ParamText(work, "\p", "\p", "\p");
- StopAlert(ALRT_NoMemory, NULL);
- return (FALSE);
- }
- /* To do: read one block to verify that everything is in place */
- return (TRUE);
- }
- }
-
- /*
- * SaveInfoRecord links this InfoRecord into the active queue.
- */
- void
- SaveInfoRecord(void)
- {
- Enqueue((QElemPtr) gCurrentInfoPtr, &infoPtrQueue);
- gCurrentInfoPtr = NULL;
- }
-
- /*
- * Get the SCSI 4.3 Exec I/O parameter block. If this succeeds,
- * INFO.pb points to the parameter block, and INFO.pbSize has
- * its length. On failure, INFO.pb is NULL and INFO.pbSize zero.
- */
- void
- RefreshParamBlock(void)
- {
- OSErr status;
- SCSIBusInquiryPB pb;
-
- CLEAR(pb);
- pb.scsiPBLength = sizeof pb;
- pb.scsiFunctionCode = SCSIBusInquiry;
- pb.scsiCompletion = NULL;
- pb.scsiFlags = 0;
- pb.scsiDevice = INFO.deviceIdent;
- SCSIAction((SCSI_PB *) &pb);
- status = pb.scsiResult;
- if (status == noErr) {
- if (INFO.pb != NULL && INFO.pbSize != pb.scsiIOpbSize) {
- DisposePtr((Ptr) INFO.pb);
- INFO.pb = NULL;
- INFO.pbSize = 0;
- }
- if (INFO.pb == NULL) {
- INFO.pb = (SCSIExecIOPB *) NewPtr(pb.scsiIOpbSize);
- if (INFO.pb == NULL)
- status = MemError();
- else {
- INFO.pbSize = pb.scsiIOpbSize;
- }
- }
- }
- if (status != noErr) {
- NonFatalError(status, "\pCan't allocate SCSI Parameter Block");
- if (INFO.pb != NULL) {
- DisposePtr((Ptr) INFO.pb);
- INFO.pb = NULL;
- INFO.pbSize = 0;
- }
- }
- }
-
- /*
- * Get the Device Inquiry (vendor, product) data. Return error status.
- */
- OSErr
- SetupDeviceInquiry(void)
- {
- OSErr status;
- SCSI_Inquiry_Data inquiryData;
- const SCSI_6_Byte_Command inquiryCmd = {
- kScsiCmdInquiry, 0, 0, 0, sizeof inquiryData, 0
- };
-
- status = DoSCSISynchronousIO(
- gCurrentInfoPtr, /* -> INFO */
- (SCSI_CommandPtr) &inquiryCmd, /* Command */
- scsiDirectionIn, /* Reading from device */
- (Ptr) &inquiryData, /* -> data buffer */
- sizeof inquiryData /* data buffer size */
- );
- if (status == noErr) {
- StoreDeviceString(INFO.vendor, inquiryData.vendor, sizeof inquiryData.vendor);
- StoreDeviceString(INFO.product, inquiryData.product, sizeof inquiryData.product);
- }
- return (status);
- }
-
- /*
- * Get the drive capacity (blocks, logical block length) for the device.
- * Return error status.
- */
- OSErr
- SetupReadCapacity(void)
- {
- OSErr status;
- SCSI_Capacity_Data capacityData;
- const SCSI_10_Byte_Command capacityCmd = {
- kScsiCmdReadCapacity, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
-
- status = DoSCSISynchronousIO(
- gCurrentInfoPtr, /* -> INFO */
- (SCSI_CommandPtr) &capacityCmd, /* Command */
- scsiDirectionIn, /* Reading from device */
- (Ptr) &capacityData, /* -> data buffer */
- sizeof capacityData /* data buffer size */
- );
- if (status == noErr) {
- INFO.totalLogicalBlocks = GetFourBytes(&capacityData.lbn4);
- INFO.logicalBlockLength = GetFourBytes(&capacityData.len4);
- }
- return (status);
- }
-
- void
- StoreDeviceString(
- unsigned char *dst,
- unsigned char *src,
- short srcLength
- )
- {
- short i;
-
- for (i = srcLength; i > 0 && src[i - 1] == ' '; --i)
- ;
- BlockMove(src, &dst[1], i);
- dst[0] = i;
- }
-
- unsigned long
- GetFourBytes(
- unsigned char *src
- )
- {
- register unsigned long result;
-
- result = src[0] & 0xFF;
- result <<= 8;
- result |= (src[1] & 0xFF);
- result <<= 8;
- result |= (src[2] & 0xFF);
- result <<= 8;
- result |= (src[3] & 0xFF);
- return (result);
- }
-